function cleanup ( res )
	if res == getThisResource () then
		for k, player in ipairs ( getElementsByType ( "player" ) ) do
			if isControlling ( player ) then
				binder ( player, false )
				outputChatBox ( "Just erasin' old target data, yo!", player )
			end
		end
	end
end
addEventHandler ( "onResourceStart", getResourceRootElement(), cleanup )
addEventHandler ( "onResourceStop", getResourceRootElement(), cleanup )


function findPlayerByNickname ( s )
	if s then
		local s = string.lower ( skipColorCode ( s ) )
		local playersMatching = {}
		for k, v in ipairs ( getElementsByType ( "player" ) ) do
			local name = getPlayerName ( v )
			local name = string.lower ( skipColorCode ( name ) )
			if name == s then
				return v 
			elseif string.find ( name, s, 1, true ) then
				table.insert ( playersMatching, v )
			end
		end
		if #playersMatching == 1 then
			return ( playersMatching [ 1 ] )
		end
	else
		return false
	end
end

function skipColorCode ( s )
	if type ( s ) == "string" then
		return string.gsub ( s, "(#%x%x%x%x%x%x)", "" )
	elseif type ( s ) == "userdata" and getElementType ( s ) == "player" then
		return string.gsub ( getPlayerName ( s ), "(#%x%x%x%x%x%x)", "" )
	end
end	

binds = {
	num_0 = { "sprint", "handbrake" },
	num_1 = { "fire", "vehicle_fire" },
	num_2 = { "enter_exit" },
	num_3 = { "crouch", "vehicle_secondary_fire" },
	num_4 = { "left", "vehicle_left" },
	num_5 = { "backwards", "brake_reverse" },
	num_6 = { "right", "vehicle_right" },
	num_7 = { "jump", "vehicle_look_left" },
	num_8 = { "forwards", "accelerate" },
	num_9 = { "aim_weapon", "vehicle_look_right" },
	num_add = { "next_weapon", "steer_forward" },-- +
	num_sub = { "previous_weapon", "steer_back" },-- -
	--num_mul = {},-- *
	num_dec = { "walk", "horn" },-- ,
	--num_div = {},-- /
}

unbinds = { "special_control_down", "special_control_right", "special_control_left", "special_control_up" }

function isControlling ( player )
	return getElementData ( player, "isControlling" )
end

function getTarget ( player )
	return getElementData ( player, "possTarget" )
end

function isMainKeyBound ( player )
	return isKeyBound ( player, "num_div", "down", preBinder )
end

addCommandHandler("poss",
	function ( player, cmd, nick )
		if not isMainKeyBound ( player ) then
			bindKey ( player, "num_div", "down", preBinder )
		end
		if nick then
			local newTarget = findPlayerByNickname ( nick )
			if newTarget then
				local target = getTarget ( player )
				if isControlling ( player ) then
					toggleAllControls ( target, true, true, false )
					outputChatBox ( "Turnin' posession of playa named " .. skipColorCode ( target ) .. " off.", player )
				end
				setElementData ( player, "possTarget", newTarget )
				outputChatBox ( "Found playa " .. skipColorCode ( newTarget ) .. ". Press \"/\" on numpad to start posession, yo!", player )
			else
				outputChatBox ( "Can't find playa by \"" .. nick .. "\", bitch!", player )
			end
		else
			outputChatBox ( "Yo, got no target. Type \"/poss <nickname>\".", player )
		end
	end
)

stateToBoolean = {
	up = false,
	down = true
}

function possSetControlState ( player, key, state, func )
	local target = getTarget ( player )
	if target then
		setControlState ( target, func, stateToBoolean [ state ] )
	else
		binder ( player, false )
		outputChatBox ( "Yo, you got no target! Turnin' off...", player )
	end
end

function toggleCamera ( player )
	if getCameraTarget ( player ) ~= player then
		setCameraTarget ( player )
	else
		local target = getTarget ( player )
		if target then
			setCameraTarget ( player, target )
		end
	end
end

function preBinder ( player )
	binder ( player )
end

function binder ( player, bool )
	local target = getTarget ( player )
	local forced = true
	if bool == nil then 
		forced = false
		if target then
			bool = not isControlling ( player )
		else
			outputChatBox ( "Choose da playa ye wanna control first, yo!", player )
			binder ( player, false )
			return
		end
	end
	if bool == true then
		for k, v in pairs ( binds ) do
			for l, b in ipairs ( v ) do
				bindKey ( player, k, "both", possSetControlState, b )
			end
		end
		bindKey ( player, "num_mul", "down", toggleCamera )
		for k, v in pairs ( unbinds ) do
			toggleControl ( player, v, false )
		end
		toggleAllControls ( target, false, true, false )
		if not forced then
			outputChatBox ( "Turned da control on playa " .. skipColorCode ( target ) .. ", yo!", player )
		end
	elseif bool == false then
		for k, v in pairs ( binds ) do
			for l, b in ipairs ( v ) do
				unbindKey ( player, k, "both", possSetControlState )
			end
		end
		unbindKey ( player, "num_mul", "down", toggleCamera )
		if getCameraTarget ( player ) ~= player then
			setCameraTarget ( player )
		end
		for k, v in pairs ( unbinds ) do
			toggleControl ( player, v, true )
		end
		if target then
			toggleAllControls ( target, true, true, false )
		end
		if not forced then
			outputChatBox ( "No more of controlling playa " .. skipColorCode ( target ) .. ", yo!", player )
		end
	end
	setElementData ( player, "isControlling", bool )
end

addEventHandler ( "onPlayerQuit", root,
	function ()
		for k, player in ipairs ( getElementsByType ( "player" ) ) do
			if getTarget ( player ) == source then
				binder ( player, false )
				outputChatBox ( "Yo, da playa named " .. skipColorCode ( source ) .. " left. Turnin' da control off!", player )
			end
		end
	end
)
